package com.candoit.webapps.pricing.controllers;

import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import javax.el.ValueExpression;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.RequestScoped;
import javax.faces.bean.SessionScoped;
import javax.faces.component.html.HtmlColumn;
import javax.faces.component.html.HtmlDataTable;
import javax.faces.component.html.HtmlInputText;
import javax.faces.component.html.HtmlOutputText;
import javax.faces.component.html.HtmlPanelGroup;
import javax.faces.component.html.HtmlSelectBooleanCheckbox;
import javax.faces.context.FacesContext;
import javax.faces.event.ValueChangeEvent;

import com.candoit.webapps.pricing.model.Categoria;
import com.candoit.webapps.pricing.model.CentroCostos;
import com.candoit.webapps.pricing.model.CentroCostosCriterio;
import com.candoit.webapps.pricing.model.CentroCostosCriterioFK;
import com.candoit.webapps.pricing.model.CriterioDistribucion;
import com.candoit.webapps.pricing.model.Cuenta;
import com.candoit.webapps.pricing.util.CentroCriterioUtil;
import com.candoit.webapps.pricing.util.CriterioDistribucionUtil;
import com.candoit.webapps.pricing.util.QueryUtil;

@ManagedBean(name = "criterioCtrl")
@SessionScoped
public class CriterioController extends AbstractController {
	
	  private HtmlPanelGroup panelProduccionGroup;
	  private List<CriterioDistribucion> criterios; 
	  private Categoria categoriaSelected;
	  private List<CentroCostos> centrosSelected;
	  private List<CriterioDistribucionUtil> listUtils;
	  private Map<Integer, CriterioDistribucionUtil> mapUtil; 
	  private Map<String, CentroCriterioUtil> mapCriterio; 
	  private CriterioDistribucionUtil utilNuevo  = null;
	  private List<CriterioDistribucionUtil> criteriosNuevos;
	  private Map<Integer, CentroCriterioUtil> mapCriterioNuevo;
	  
	  public void saveCriterios(){
		Iterator<CriterioDistribucionUtil> it = listUtils.iterator();
		while (it.hasNext()){
			CriterioDistribucionUtil centroCriterio = (CriterioDistribucionUtil) it.next();
			if (centroCriterio.getCriterio().getId() != null){
				this.update(centroCriterio.getCriterio());
				for (CentroCriterioUtil util : centroCriterio.getDistribuciones()){
					 if(centroCriterio.getCriterio().getId() != null){	
						this.update(util.getDistribucion());
					 }
				}
			}else{
				if (centroCriterio.getCriterio().getDescripcion() != null && !centroCriterio.getCriterio().getDescripcion().equals("")){
					this.save(centroCriterio.getCriterio());
					for (CentroCriterioUtil util : centroCriterio.getDistribuciones()){
							this.save(util.getDistribucion());
					}
				 }
			}
			
		}
		this.reLoadDynamicList();
		FacesContext.getCurrentInstance().renderResponse();
		try {
			FacesContext.getCurrentInstance().getExternalContext().redirect("admin-criterios.jsf");
		} catch (IOException e) {
			e.printStackTrace();
		}
	 }
	 
	  public void borrarCriterios(){
			List<CriterioDistribucionUtil> listAux = listUtils;
			Iterator<CriterioDistribucionUtil> it = listAux.iterator();
			while (it.hasNext()){
				CriterioDistribucionUtil centroCriterio = (CriterioDistribucionUtil) it.next();
					if (centroCriterio.getSelected() == true){
						if (centroCriterio.getCriterio().getId() != null){	
							List<Cuenta> cuentas = QueryUtil.getInstance().getCuentaByCriterio(centroCriterio.getCriterio());
							for (Cuenta cuenta : cuentas){
								cuenta.setCriterio(null);
								this.update(cuenta);
							}

							List<CentroCostosCriterio> centros = QueryUtil.getInstance().getCentroCostoCriterioByCriterio(centroCriterio.getCriterio());
							for (CentroCostosCriterio cc : centros){
								this.remove(cc);
							}	
							this.remove(centroCriterio.getCriterio());
						}
					} 	
			}
			this.reLoadDynamicList();
			FacesContext.getCurrentInstance().renderResponse();
			try {
				FacesContext.getCurrentInstance().getExternalContext().redirect("admin-criterios.jsf");
			} catch (IOException e) {
				e.printStackTrace();
			}	
		 	
	  }
	  

	 private void loadDynamicList() {
		  	criterios = QueryUtil.getInstance().getCriterios();
		  	this.fillTablas();
		}

	    private void populateDynamicDataTable() {
	    	panelProduccionGroup = new HtmlPanelGroup();
	    	String clasesColumn = "evencriterio, evencriterio, evencriterio,evencriterio";
	    	List<CentroCostos> centrosSelected = getCentrosSelected();
	    	for (int i = 0; i < centrosSelected.size(); i++) {
				clasesColumn += ", evencriterio";
			}
	    	int i = 0;
	    	HtmlDataTable dynamicDataTable = this.fillInputsCriterio(i, clasesColumn);
	        panelProduccionGroup.getChildren().add(dynamicDataTable);
	        i++;
	    	
        }	        

	    public HtmlPanelGroup getPanelProduccionGroup() {
//	    	if (panelProduccionGroup == null && isFirstCall) {
	            loadDynamicList(); 
	            populateDynamicDataTable(); 
//	        }

	        return panelProduccionGroup;
	    }

	    public void setPanelProduccionGroup(HtmlPanelGroup panelProduccionGroup) {
	        this.panelProduccionGroup = panelProduccionGroup;
	    }

		public List<CriterioDistribucion> getCriterios() {
			criterios = QueryUtil.getInstance().getCriterios();
			return criterios;
		}

		public void setCriterios(List<CriterioDistribucion> criterios) {
			this.criterios = criterios;
		}
		
		public Categoria getCategoriaSelected() {
			return categoriaSelected;
		}

		public void setCategoriaSelected(Categoria categoriaSelected) {
			this.categoriaSelected = categoriaSelected;
		}
		
		public List<CriterioDistribucionUtil> getCriteriosNuevos() {
			return criteriosNuevos;
		}

		public void setCriteriosNuevos(List<CriterioDistribucionUtil> criteriosNuevos) {
			this.criteriosNuevos = criteriosNuevos;
		}
		
		public Map<Integer, CentroCriterioUtil> getMapCriterioNuevo() {
			return mapCriterioNuevo;
		}

		public void setMapCriterioNuevo(
				Map<Integer, CentroCriterioUtil> mapCriterioNuevo) {
			this.mapCriterioNuevo = mapCriterioNuevo;
		}

		private ValueExpression createValueExpression(String valueExpression,
                Class<?> valueType) {
			 FacesContext facesContext = FacesContext.getCurrentInstance();
		        return facesContext.getApplication().getExpressionFactory().createValueExpression(
		                facesContext.getELContext(), valueExpression, valueType);
		}
		      
		public List<CentroCostos> getCentrosSelected() {
			if (categoriaSelected == null || categoriaSelected.getId() == Categoria.PRODUCTION_CODE){
				centrosSelected = QueryUtil.getInstance().getCentroCostosByCategoria(Categoria.PRODUCTION_CODE);
			}else{
				centrosSelected = QueryUtil.getInstance().getCentroCostosByCategoria(categoriaSelected.getId());
			}
			return centrosSelected;
		}

		public void setCentrosSelected(List<CentroCostos> centrosSelected) {
			this.centrosSelected = centrosSelected;
		}
		
		public List<CriterioDistribucionUtil> getListUtils() {
			return listUtils;
		}

		public void setListUtils(List<CriterioDistribucionUtil> listUtils) {
			this.listUtils = listUtils;
		}
		
		public Map<Integer, CriterioDistribucionUtil> getMapUtil() {
			return mapUtil;
		}

		public void setMapUtil(Map<Integer, CriterioDistribucionUtil> mapUtil) {
			this.mapUtil = mapUtil;
		}
		
		public Map<String, CentroCriterioUtil> getMapCriterio() {
			return mapCriterio;
		}

		public void setMapCriterio(Map<String, CentroCriterioUtil> mapCriterio) {
			this.mapCriterio = mapCriterio;
		}
		
		public CriterioDistribucionUtil getUtilNuevo() {
			return utilNuevo;
		}

		public void setUtilNuevo(CriterioDistribucionUtil utilNuevo) {
			this.utilNuevo = utilNuevo;
		}
		
		private void fillTablas(){
			listUtils = new ArrayList<CriterioDistribucionUtil>();
			criteriosNuevos = new ArrayList<CriterioDistribucionUtil>();
			mapUtil = new HashMap<Integer, CriterioDistribucionUtil>();
			mapCriterio = new HashMap<String, CentroCriterioUtil>();
			mapCriterioNuevo = new HashMap<Integer, CentroCriterioUtil>();
			for (CriterioDistribucion criterio : getCriterios()){
				CriterioDistribucionUtil util = new CriterioDistribucionUtil();
				util.setCriterio(criterio);
				util.setIdCriterio(criterio.getId());
				util.setTotalAsignado(QueryUtil.getInstance().getTotalAsignadoCriterio(criterio));
				util.setSelected(false);
				for (CentroCostos centro : getCentrosSelected()){
					CentroCostosCriterio cc = QueryUtil.getInstance().getCentroCostosCriterioObject(centro, criterio);
					if (cc == null){
						cc = new CentroCostosCriterio();
						cc.setCantidad(0.00d);
						CentroCostosCriterioFK fk = new CentroCostosCriterioFK();
						fk.setCentro(centro);fk.setCriterio(criterio);
						cc.setFk(fk);
					}
					double perc =0.00d;
					if (util != null && util.getTotalAsignado() != null && util.getTotalAsignado() > 0){	
						perc = cc.getCantidad()* 100 / util.getTotalAsignado();
					}
					CentroCriterioUtil dist = new CentroCriterioUtil();
					dist.setDistribucion(cc);
					dist.setPorcentaje(perc);
					if (cc.getFk().getCriterio().getId() != null){
						dist.setIdCriterio(cc.getFk().getCriterio().getId());
					}else{
						dist.setIdCriterio(0);
					}
					if (util.getDistribuciones() == null){
						util.setDistribuciones(new ArrayList<CentroCriterioUtil>());
					}
					util.getDistribuciones().add(dist);
					mapUtil.put(criterio.getId(), util);
					mapCriterio.put(String.valueOf(util.getIdCriterio()) + String.valueOf(centro.getId()) , dist);
				}
				
				listUtils.add(util);
			}
			
			CriterioDistribucionUtil utilNuevo = new CriterioDistribucionUtil();
			CriterioDistribucion criterio = new CriterioDistribucion();
			utilNuevo.setTotalAsignado(0.00d);
			utilNuevo.setCriterio(criterio);
			utilNuevo.setIdCriterio(0);
			utilNuevo.setSelected(false);
			for (CentroCostos centro : getCentrosSelected()){
				CentroCostosCriterio cc = new CentroCostosCriterio();
				cc.setCantidad(0.00d);
				CentroCostosCriterioFK fk = new CentroCostosCriterioFK();
				fk.setCentro(centro);fk.setCriterio(criterio);
				cc.setFk(fk);
				CentroCriterioUtil dist = new CentroCriterioUtil();
				dist.setDistribucion(cc);
				dist.setPorcentaje(0.00d);
				if (utilNuevo.getDistribuciones() == null){
					utilNuevo.setDistribuciones(new ArrayList<CentroCriterioUtil>());
				}
				utilNuevo.getDistribuciones().add(dist);
				mapCriterio.put(String.valueOf(utilNuevo.getIdCriterio()) + String.valueOf(centro.getId()) , dist);
			}
			
			listUtils.add(utilNuevo);
		}
		
		public List<CriterioDistribucionUtil> listDetail(Integer id){
			List<CriterioDistribucionUtil> list = new ArrayList<CriterioDistribucionUtil>();
			CriterioDistribucionUtil util = mapUtil.get(id);
			list.add(util);
			return list;
		}
		
		public CentroCriterioUtil getCentroCriterio(CriterioDistribucionUtil criterio, String id){
			return mapCriterio.get(String.valueOf(criterio.getIdCriterio()) + id);
		}
		
		public CentroCriterioUtil getCentroCriterioNuevo(Integer id){
			return mapCriterioNuevo.get(id);
		}
		
		public void reLoadDynamicList() {
		  	criterios = QueryUtil.getInstance().getCriterios();
		  	this.fillTablas();
		  	populateDynamicDataTable();
		}
		
		public void valueChanged(ValueChangeEvent event) {
	        if (null != event.getNewValue()) {
	        	this.categoriaSelected = (Categoria)event.getNewValue(); 
	        	reLoadDynamicList();
	        	FacesContext.getCurrentInstance().renderResponse();
	        	try {
					FacesContext.getCurrentInstance().getExternalContext().redirect("admin-criterios.jsf");
				} catch (IOException e) {
					e.printStackTrace();
				}

	        	
	        }
	    }
		
		private HtmlDataTable fillInputsCriterio(int fila, String columnClases){
   		 
		 HtmlDataTable dynamicDataTable = new HtmlDataTable();
      	 dynamicDataTable.setColumnClasses(columnClases);
      	 dynamicDataTable.setId("tabla");
	     dynamicDataTable.setHeaderClass("headingcriterio");
	     dynamicDataTable.setStyleClass("mainTable");
		 dynamicDataTable.setValueExpression("value",createValueExpression("#{criterioCtrl.listUtils}", List.class));
	     dynamicDataTable.setVar("item");
	     HtmlColumn columnSelected = new HtmlColumn();
	     HtmlOutputText headerSelected = new HtmlOutputText();
	     headerSelected.setValue("");
	     columnSelected.setHeader(headerSelected);
	     HtmlSelectBooleanCheckbox select = new HtmlSelectBooleanCheckbox();
	     select.setValueExpression("value", createValueExpression("#{item.selected}",Boolean.class));
	     columnSelected.getChildren().add(select);   
	     dynamicDataTable.getChildren().add(columnSelected);
	     HtmlColumn column = new HtmlColumn();
	     HtmlOutputText header = new HtmlOutputText();
	     header.setValue("Criterio");
	     column.setHeader(header);
	     HtmlInputText nombreCriterio = new HtmlInputText();
	     nombreCriterio.setValueExpression("value", createValueExpression("#{item.criterio.descripcion}",String.class));
	     column.getChildren().add(nombreCriterio);
	     HtmlOutputText nombreCriterioOutput = new HtmlOutputText();
	     nombreCriterioOutput.setValue("Porcentajes");
	     nombreCriterioOutput.setEscape(false);
	     column.getChildren().add(nombreCriterioOutput);
	     dynamicDataTable.getChildren().add(column);
	     HtmlColumn columnUnidad = new HtmlColumn();
         HtmlOutputText headerUnidad = new HtmlOutputText();
         headerUnidad.setValue("Unidad");
	     columnUnidad.setHeader(headerUnidad);
	     HtmlInputText nombreUnidad = new HtmlInputText();
	     nombreUnidad.setValueExpression("value", createValueExpression("#{item.criterio.unidad}",String.class));
	     columnUnidad.getChildren().add(nombreUnidad);
         dynamicDataTable.getChildren().add(columnUnidad);         
         HtmlColumn columnAsignado = new HtmlColumn();
         HtmlOutputText headerAsignado = new HtmlOutputText();
         headerAsignado.setValue("Total Asignado");
	     columnAsignado.setHeader(headerAsignado);
         HtmlOutputText asignado = new HtmlOutputText();
         asignado.setValueExpression("value",createValueExpression("#{item.totalAsignado}",Double.class));
         columnAsignado.getChildren().add(asignado);
         HtmlOutputText lineBreak = new HtmlOutputText();
         lineBreak.setValue("<br/>");
         lineBreak.setEscape(false);
         columnAsignado.getChildren().add(lineBreak);
         HtmlOutputText outputTotalAsignado = new HtmlOutputText();
         outputTotalAsignado.setValue("100%");
         outputTotalAsignado.setEscape(false);
         columnAsignado.getChildren().add(outputTotalAsignado);
         dynamicDataTable.getChildren().add(columnAsignado);
         for(CentroCostos centro : getCentrosSelected()){
         	HtmlColumn columnDistribucion = new HtmlColumn();
         	HtmlOutputText headerDist = new HtmlOutputText();
         	headerDist.setValue(centro.getNombre());
 	        columnDistribucion.setHeader(headerDist);
 	        HtmlInputText distribucion = new HtmlInputText();
 	        distribucion.setValueExpression("value", createValueExpression("#{criterioCtrl.getCentroCriterio(item, " +  String.valueOf(centro.getId()) +").distribucion.cantidad}",Double.class));
  	        columnDistribucion.getChildren().add(distribucion); 
  	        HtmlOutputText distribucionOutput = new HtmlOutputText();
  	  	   	distribucionOutput.setValueExpression("value", createValueExpression("#{criterioCtrl.getCentroCriterio( item, " +  String.valueOf(centro.getId()) +").porcentajeMsg}",String.class));
  	       	columnDistribucion.getChildren().add(distribucionOutput);
  	       	dynamicDataTable.getChildren().add(columnDistribucion);
         }
         
         return dynamicDataTable;
			
		}
		
		
}
